package com.ruibang.glass.material.service.impl.bcp;


import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ruibang.glass.common.constants.RedisKey;
import com.ruibang.glass.common.domain.DictInfo;
import com.ruibang.glass.common.domain.camunda.BpmProcessInstanceCreate;
import com.ruibang.glass.common.domain.camunda.BpmProcessInstanceStatus;
import com.ruibang.glass.common.domain.sale.SaleOrderManagement;
import com.ruibang.glass.common.utils.ApproveUserNameUtils;
import com.ruibang.glass.frequencycontrol.annotation.RedissonLock;
import com.ruibang.glass.material.constant.Constants;
import com.ruibang.glass.material.constant.MaterialStatusCode;
import com.ruibang.glass.material.constant.MaterialWareHouseCode;
import com.ruibang.glass.material.domain.req.bcp.BcpProductsInfoReq;
import com.ruibang.glass.material.entity.MaterialALLInventoryManagement;
import com.ruibang.glass.material.entity.MaterialContentLot;
import com.ruibang.glass.material.entity.MaterialCpBcpItems;
import com.ruibang.glass.material.entity.bcp.MaterialBcpProductsInInfo;
import com.ruibang.glass.material.entity.cp.MaterialCPProductsInInfo;
import com.ruibang.glass.material.feign.CamundaApi;
import com.ruibang.glass.material.feign.PortalApi;
import com.ruibang.glass.material.feign.SaleApi;
import com.ruibang.glass.material.mapper.MaterialCpBcpItemsMapper;
import com.ruibang.glass.material.mapper.bcp.MaterialBcpProductsInInfoMapper;
import com.ruibang.glass.material.mapper.bcp.MaterialBcpProductsOutMapper;
import com.ruibang.glass.material.service.GMaterialALLInventoryManagementService;
import com.ruibang.glass.material.service.MaterialContentLotService;
import com.ruibang.glass.material.service.SerialINNumberGenerator;
import com.ruibang.glass.material.service.bcp.MaterialBcpProductsInInfoService;
import com.ruibang.glass.material.service.bcp.MaterialBcpProductsInService;
import com.ruibang.glass.material.service.impl.CommonService;
import com.teaming.cloud.framework2.autoconfigure.redis.RedisSingleService;
import com.teaming.cloud.framework2.common.constant.CommonConstant;
import com.teaming.cloud.framework2.common.exception.ServiceException;
import com.teaming.cloud.framework2.common.model.ResultBody;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.support.TransactionTemplate;

import java.io.Serializable;
import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.stream.Collectors;

import static com.ruibang.glass.common.constants.RedisKey.MATERIAL_IN_WAREHOUSE_NUMBER;

/**
 * <p>
 * 半成品入库详情 服务实现类
 * </p>
 *
 * @author mameng
 * @since 2024-04-02
 */
@Service
public class GMaterialBcpProductsInInfoServiceImpl extends ServiceImpl<MaterialBcpProductsInInfoMapper, MaterialBcpProductsInInfo> implements MaterialBcpProductsInInfoService {

    @Autowired
    private CommonService commonService;

    @Autowired
    private CamundaApi camundaApi;

    @Autowired
    private MaterialBcpProductsInService materialBcpProductsInService;

    @Autowired
    private RedisSingleService redisService;

    private static final String PURCHASE_IN_NUMBER = "purchase_in_number";

    @Autowired
    private GMaterialALLInventoryManagementService materialALLInventoryManagementService;


    @Autowired
    private MaterialContentLotService materialContentLotService;

    private final String BCPMENUID = "w0235dokc6a011a6f2b5840cea000028";

    @Autowired
    private MaterialCpBcpItemsMapper materialCpBcpItemsMapper;

    @Autowired
    private PortalApi portalApi;

    @Autowired
    private SaleApi saleApi;

    @Autowired
    private TransactionTemplate transactionTemplate;

    @Autowired
    private MaterialBcpProductsOutMapper materialBcpProductsOutMapper;


    /**
     * @param bcpProductsInfoReq
     * @return
     */
    @Override
    public IPage<MaterialBcpProductsInInfo> getPage(BcpProductsInfoReq bcpProductsInfoReq) {
        LambdaQueryWrapper<MaterialBcpProductsInInfo> queryWrapper = Wrappers.<MaterialBcpProductsInInfo>lambdaQuery();
        if (StringUtils.isNotBlank(bcpProductsInfoReq.getInStorageOrderNo())) {
            queryWrapper.like(MaterialBcpProductsInInfo::getInStorageOrderNo, bcpProductsInfoReq.getInStorageOrderNo());
        }
        if (StringUtils.isNotBlank(bcpProductsInfoReq.getPreparer())) {
            queryWrapper.like(MaterialBcpProductsInInfo::getPreparer, bcpProductsInfoReq.getPreparer());
        }
        if (StringUtils.isNotBlank(bcpProductsInfoReq.getStatus())) {
            queryWrapper.like(MaterialBcpProductsInInfo::getStatus, bcpProductsInfoReq.getStatus());
        }
        if (StringUtils.isNotBlank(bcpProductsInfoReq.getType())) {
            queryWrapper.like(MaterialBcpProductsInInfo::getType, bcpProductsInfoReq.getType());
        }
        if (StringUtils.isNotBlank(bcpProductsInfoReq.getApproveStatus())) {
            queryWrapper.like(MaterialBcpProductsInInfo::getApproveStatus, bcpProductsInfoReq.getApproveStatus());
        }

        if (bcpProductsInfoReq.getInCreationEndTime() != null) {
            queryWrapper.le(MaterialBcpProductsInInfo::getInCreationTime, bcpProductsInfoReq.getInCreationEndTime());
        }
        if (bcpProductsInfoReq.getInCreationStartTime() != null) {
            queryWrapper.ge(MaterialBcpProductsInInfo::getInCreationTime, bcpProductsInfoReq.getInCreationStartTime());
        }
        Page<MaterialBcpProductsInInfo> materialWarehouseInfoPage = baseMapper.selectPage(new Page<>(bcpProductsInfoReq.getPageNo(), bcpProductsInfoReq.getPageSize()),
                queryWrapper.orderByDesc(MaterialBcpProductsInInfo::getCreateTime)
        );
        if (CollectionUtils.isEmpty(materialWarehouseInfoPage.getRecords())) {
            return materialWarehouseInfoPage;
        }
        Map<Object, Object> userMap = redisService.hmget(RedisKey.USER_GROUP_TYPE);
        List<String> businessKeys = materialWarehouseInfoPage.getRecords().stream().map(MaterialBcpProductsInInfo::getId).collect(Collectors.toList());
        Map<String, BpmProcessInstanceStatus> processMap = null;
        //获取业务流程状态
        ResultBody<List<BpmProcessInstanceStatus>> resultBody = camundaApi.queryProcessInstanceStatus(businessKeys);
        if (resultBody != null && CollectionUtils.isNotEmpty(resultBody.getData())) {
            processMap = resultBody.getData().stream().collect(Collectors.toMap(bp -> bp.getBusinessKey(), bp -> bp, (bp1, bp2) -> bp1));
        }


        for (MaterialBcpProductsInInfo materialBcpProductsInInfo : materialWarehouseInfoPage.getRecords()) {
            List<MaterialCpBcpItems> materialCpBcpItemsList = materialCpBcpItemsMapper.selectList(Wrappers.<MaterialCpBcpItems>lambdaQuery().select(MaterialCpBcpItems::getWarehouseName, MaterialCpBcpItems::getId).eq(MaterialCpBcpItems::getCpBcpId, materialBcpProductsInInfo.getId()));
            String warehouseString = "";
            StringBuilder sb = new StringBuilder(); // 使用StringBuilder来构建字符串
            for (MaterialCpBcpItems materialCpBcpItems : materialCpBcpItemsList) {
                if (StringUtils.isNotEmpty(materialCpBcpItems.getWarehouseName())) {
                    if (sb.length() > 0) {
                        // 如果StringBuilder已经有内容了，就添加一个逗号
                        sb.append(",");
                    }
                    // 添加仓库名
                    sb.append(materialCpBcpItems.getWarehouseName());
                }
            }
            warehouseString = sb.toString();
            materialBcpProductsInInfo.setWarehouseName(warehouseString);
            if (processMap != null) {
                if (processMap.get(materialBcpProductsInInfo.getId()) != null) {
                    if (processMap.get(materialBcpProductsInInfo.getId()).getStatus()!=null){
                        materialBcpProductsInInfo.setStatus(String.valueOf(processMap.get(materialBcpProductsInInfo.getId()).getStatus()));
                    }
                    materialBcpProductsInInfo.setProcessId(processMap.get(materialBcpProductsInInfo.getId()).getProcessInstanceId());
//                    materialBcpProductsInInfo.setApproveStatus(processMap.get(materialBcpProductsInInfo.getId()).getResult());
                    materialBcpProductsInInfo.setNodeName(processMap.get(materialBcpProductsInInfo.getId()).getNodeName());
                    String userId = processMap.get(materialBcpProductsInInfo.getId()).getUserId();
                    if (StringUtils.isNotEmpty(userId) && !StringUtils.equals(userId, "null")) {
                        String approveName = ApproveUserNameUtils.getApproveName(userId, userMap);
                        materialBcpProductsInInfo.setApproveUser(approveName);
                        materialBcpProductsInInfo.setApproveUserId(userId);
                    }
//                if (StringUtils.isNotEmpty(userId)) {
//                    materialBcpProductsInInfo.setApproveUser(userMap.get(userId).toString());
//                }
                }
            }

        }
        return materialWarehouseInfoPage;
    }

    /**
     * 新建流程
     *
     * @param materialBcpProductsInInfos
     */
    @Override
    public void addMaterialBcpProductsInInfoList(List<MaterialBcpProductsInInfo> materialBcpProductsInInfos) {
        List<MaterialBcpProductsInInfo> execute = transactionTemplate.execute(tran -> {
            for (MaterialBcpProductsInInfo materialBcpProductsInInfo : materialBcpProductsInInfos) {
                materialBcpProductsInService.removeById(materialBcpProductsInInfo.getId());
                materialBcpProductsInInfo.setId("");
                baseMapper.insert(materialBcpProductsInInfo);

                if (StringUtils.isNotEmpty(materialBcpProductsInInfo.getLotId())) {
                    MaterialContentLot byId = materialContentLotService.getById(materialBcpProductsInInfo.getLotId());
                    byId.setInStatus(Constants.EIGHT_STR);
                    materialContentLotService.updateById(byId);
                }
                if (CollectionUtils.isNotEmpty(materialBcpProductsInInfo.getMaterialCpBcpItemsList())) {
                    for (MaterialCpBcpItems materialCpBcpItems : materialBcpProductsInInfo.getMaterialCpBcpItemsList()) {
                        if (StringUtils.isNotEmpty(materialCpBcpItems.getLotId())) {
                            MaterialContentLot byId = materialContentLotService.getById(materialCpBcpItems.getLotId());
                            byId.setInStatus(Constants.EIGHT_STR);
                            materialContentLotService.updateById(byId);
                        }

                        if (StringUtils.isNotEmpty(materialCpBcpItems.getATypeShelf())) {
                            MaterialALLInventoryManagement one = materialALLInventoryManagementService.getOne(Wrappers.<MaterialALLInventoryManagement>lambdaQuery()
                                    .eq(MaterialALLInventoryManagement::getATypeShelf, materialCpBcpItems.getATypeShelf())
                                    .isNotNull(MaterialALLInventoryManagement::getWareHouseName)
                                    .isNotNull(MaterialALLInventoryManagement::getWareHouseId)
                                    .isNotNull(MaterialALLInventoryManagement::getMaterialName)
                                    .isNotNull(MaterialALLInventoryManagement::getMaterialId)
                                    .isNotNull(MaterialALLInventoryManagement::getUnit)
                                    .isNotNull(MaterialALLInventoryManagement::getModelGrade)

                                    .orderByDesc(MaterialALLInventoryManagement::getCreateTime)
                                    .last("limit 1")
                            );
                            if (one != null) {
                                if (StringUtils.isEmpty(materialCpBcpItems.getWarehouseName())){
                                    materialCpBcpItems.setWarehouseName(one.getWareHouseName());
                                }
                                if (StringUtils.isEmpty(materialCpBcpItems.getWarehouseId())){
                                    materialCpBcpItems.setWarehouseId(one.getWareHouseId());
                                }
                                if (StringUtils.isEmpty(materialCpBcpItems.getItemName())){
                                    materialCpBcpItems.setItemName(one.getMaterialName());
                                }
                                if (StringUtils.isEmpty(materialCpBcpItems.getItemCode())){
                                    materialCpBcpItems.setItemCode(one.getMaterialId());
                                }
                                if (StringUtils.isEmpty(materialCpBcpItems.getUnit())){
                                    materialCpBcpItems.setUnit(one.getUnit());
                                }
                                if (StringUtils.isEmpty(materialCpBcpItems.getBatchNumber())){
                                    materialCpBcpItems.setBatchNumber(one.getBatchNumber());
                                }
                                if (StringUtils.isEmpty(materialCpBcpItems.getModelGrade())){
                                    materialCpBcpItems.setModelGrade(one.getModelGrade());
                                }
                            }
                        }

                        materialCpBcpItems.setCpBcpId(materialBcpProductsInInfo.getId());
                        materialCpBcpItemsMapper.insert(materialCpBcpItems);
                    }
                }
                // 更新退换货cpbcpId
                materialBcpProductsOutMapper.updateCPBCPId(materialBcpProductsInInfo.getInStorageOrderNo(),materialBcpProductsInInfo.getId());
            }
            return materialBcpProductsInInfos;
        });
        if (CollectionUtils.isNotEmpty(materialBcpProductsInInfos)) {
//            for (MaterialBcpProductsInInfo materialBcpProductsInInfo : materialBcpProductsInInfos) {
//                BpmProcessInstanceCreate instanceCreate = new BpmProcessInstanceCreate();
//                instanceCreate.setBusinessKey(materialBcpProductsInInfo.getId());
//                if (StringUtils.isEmpty(materialBcpProductsInInfo.getMenuId())) {
//                    materialBcpProductsInInfo.setMenuId(BCPMENUID);
//                }
//                instanceCreate.setMenuId(materialBcpProductsInInfo.getMenuId());
//                //发起流程
//                if (StringUtils.isNotBlank(materialBcpProductsInInfo.getPreparerId())) {
//                    Map<String, Object> variables = new HashMap<>();
//                    variables.put(com.ruibang.glass.common.constants.Constants.PROCESS_INSTANCE_STARTER_USER_ID, materialBcpProductsInInfo.getPreparerId());
//                    variables.put(com.ruibang.glass.common.constants.Constants.PROCESS_INSTANCE_BUSINESS_KEY, materialBcpProductsInInfo.getId());
//                    variables.put(com.ruibang.glass.common.constants.Constants.PROCESS_INSTANCE_MENU_ID, materialBcpProductsInInfo.getMenuId());
//                    instanceCreate.setVariables(variables);
//                }
//                commonService.startProcess(instanceCreate);
//            }
        }
    }



    @Override
    public void updateMaterialBcpProductsInInfo(MaterialBcpProductsInInfo materialBcpProductsInInfo) {
        baseMapper.updateById(materialBcpProductsInInfo);
        if (CollectionUtils.isNotEmpty(materialBcpProductsInInfo.getMaterialCpBcpItemsList())) {
            for (MaterialCpBcpItems materialCpBcpItems : materialBcpProductsInInfo.getMaterialCpBcpItemsList()) {
                materialCpBcpItemsMapper.updateById(materialCpBcpItems);
            }
        }

    }

    /**
     * 库存计算
     *
     * @param materialManagementInventory
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateInHouse(MaterialBcpProductsInInfo materialManagementInventory) {
//        //检验流程是否结束
        MaterialBcpProductsInInfo materialBcpJManagementInventory = baseMapper.selectById(materialManagementInventory.getId());

        List<MaterialCpBcpItems> materialCpBcpItemsList = materialCpBcpItemsMapper.selectList(Wrappers.<MaterialCpBcpItems>lambdaQuery().eq(MaterialCpBcpItems::getCpBcpId, materialManagementInventory.getId()));

        for (MaterialCpBcpItems materialCpBcpItems : materialCpBcpItemsList) {
            if (StringUtils.isBlank(materialCpBcpItems.getATypeShelf())) {
                throw new ServiceException(MaterialStatusCode.NO_A_TYPE_LIST_NUMBER.getCode(), MaterialStatusCode.NO_A_TYPE_LIST_NUMBER.getMsg());
            }
        }
        List<SaleOrderManagement> saleOrderManagementList = new ArrayList<>();
        for (MaterialCpBcpItems materialCpBcpItems : materialCpBcpItemsList) {
            if (StringUtils.isNotEmpty(materialCpBcpItems.getLotId())) {
                MaterialContentLot byId = materialContentLotService.getById(materialCpBcpItems.getLotId());
                byId.setInStatus(Constants.TEN_STR);
                materialContentLotService.updateById(byId);
            }

            if (StringUtils.isNotEmpty(materialCpBcpItems.getReturnId())) {
                SaleOrderManagement saleOrderManagement = new SaleOrderManagement();
                saleOrderManagement.setId(materialCpBcpItems.getReturnId());
                saleOrderManagement.setOrderId(materialCpBcpItems.getOrderId());
                saleOrderManagement.setReturnQuantity(BigDecimal.valueOf(materialCpBcpItems.getQuantity()));
                if (StringUtils.isNotEmpty(saleOrderManagement.getOrderId())) {
                    saleOrderManagementList.add(saleOrderManagement);
                }
            }

            MaterialALLInventoryManagement materialALLInventoryManagement = new MaterialALLInventoryManagement();
            materialALLInventoryManagement.setMaterialName(materialCpBcpItems.getItemName());
            materialALLInventoryManagement.setMaterialCode(materialCpBcpItems.getItemCode());
            materialALLInventoryManagement.setStockQuantity(materialCpBcpItems.getQuantity());
            materialALLInventoryManagement.setMaterialId(materialCpBcpItems.getItemId());
            materialALLInventoryManagement.setSpecification(materialCpBcpItems.getSpecification());
            materialALLInventoryManagement.setBatchNumber(materialCpBcpItems.getBatchNumber());
            materialALLInventoryManagement.setUnit(materialCpBcpItems.getUnit());
            materialALLInventoryManagement.setStorageLocation(materialCpBcpItems.getStorageLocationId());
            materialALLInventoryManagement.setProductionDate(materialCpBcpItems.getProductionDate());
            materialALLInventoryManagement.setExpirationDate(materialCpBcpItems.getExpirationDate());
            materialALLInventoryManagement.setInventoryDate(LocalDateTime.now());
            materialALLInventoryManagement.setWareHouseCode(MaterialWareHouseCode.BCPK_CK.getMsg());
            materialALLInventoryManagement.setWareHouseName(materialCpBcpItems.getWarehouseName());
            materialALLInventoryManagement.setWareHouseId(materialCpBcpItems.getWarehouseId());
            materialALLInventoryManagement.setATypeShelf(materialCpBcpItems.getATypeShelf());
            materialALLInventoryManagement.setModelGrade(materialCpBcpItems.getModelGrade());
            materialALLInventoryManagementService.save(materialALLInventoryManagement);
        }
        if (CollectionUtils.isNotEmpty(saleOrderManagementList)) {
            saleApi.updateGSaleReturnInventoryReQuality(saleOrderManagementList);
        }
        materialBcpJManagementInventory.setFinishDate(LocalDateTime.now());
        materialBcpJManagementInventory.setInStatus(Constants.TWO_STR);
        baseMapper.updateById(materialBcpJManagementInventory);
    }

    @Override
    public MaterialBcpProductsInInfo getMaterialBcpProductsInInfoById(String id) {
        MaterialBcpProductsInInfo bcpProductsInInfo = baseMapper.selectById(id);
        List<MaterialCpBcpItems> materialCpBcpItems = materialCpBcpItemsMapper.selectList(Wrappers.<MaterialCpBcpItems>lambdaQuery().eq(MaterialCpBcpItems::getCpBcpId, id));
        bcpProductsInInfo.setMaterialCpBcpItemsList(materialCpBcpItems);
        return bcpProductsInInfo;
    }


    public String getApproveStatus(String id) {
        ResultBody<List<BpmProcessInstanceStatus>> resultBody = camundaApi.queryProcessInstanceStatus(Arrays.asList(id));
        Map<String, String> approveStatusMap = null;
        if (resultBody != null && CollectionUtils.isNotEmpty(resultBody.getData())) {
            approveStatusMap = resultBody.getData().stream().collect(Collectors.toMap(BpmProcessInstanceStatus::getBusinessKey, BpmProcessInstanceStatus::getResult, (s1, s2) -> s1));
        }
        if (approveStatusMap.get(id) != null) {
            return approveStatusMap.get(id);
        }
        return "";
    }

    @Override
    public String getINNumber() {
        String materialInNumber = getMaterialInNumber();
        return materialInNumber;
    }

    @RedissonLock(key = MATERIAL_IN_WAREHOUSE_NUMBER, prefixKey = "lock_")
    public String getMaterialInNumber() {
        String date = LocalDate.now().format(DateTimeFormatter.ofPattern(CommonConstant.DATE_FORMAT_UN_SEPARATE));
        date = "IN".concat(date);
        String code = "";

        Serializable number = redisService.get(RedisKey.MATERIAL_IN_WAREHOUSE_NUMBER);
        if (number == null || StringUtils.isBlank(number.toString())) {
            ResultBody<String> resultBody = portalApi.getValueByCode(PURCHASE_IN_NUMBER);
            if (resultBody != null && StringUtils.isNotBlank(resultBody.getData())) {
                number = resultBody.getData();
            }
        }
        if (number != null && StringUtils.isNotBlank(number.toString()) && number.toString().length() > 10) {
            String sequenceStr = number.toString().substring(10);
            int sequenceInt = Integer.parseInt(sequenceStr);
            sequenceInt = sequenceInt + 1;
            String newSequence = String.valueOf(sequenceInt);
            if (newSequence.length() == CommonConstant.FIVE_INT) {
                code = date.concat("0001");
            } else {
                code = date.concat(String.format("%04d", sequenceInt)); // 格式化数字为4位，不足部分用0填充
            }
        } else {
            code = date.concat("0001");
        }
        redisService.set(RedisKey.MATERIAL_IN_WAREHOUSE_NUMBER, code);
        DictInfo info = new DictInfo();
        info.setCsdm(RedisKey.MATERIAL_IN_WAREHOUSE_NUMBER);
        info.setCsmc(code);
        portalApi.updateValueByCode(info);
        return code;
    }


}
